package xj.graph2d;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class PrintManager {

  public PrintManager(View view, PageFormat pf) throws PrinterException {
    this.view = view;
    this.pf = pf;
    // reset();
  }

  public void reset() {
    if (view != null && pf != null) {
      paperWidth = (int) pf.getWidth();
      paperHeight = (int) pf.getHeight();
      pageWidth = (int) pf.getImageableWidth();
      pageHeight = (int) pf.getImageableHeight();
      pageX = (int) pf.getImageableX();
      pageY = (int) pf.getImageableY();
      Rectangle2D r = null;
      Document doc = view.getDocument();
      if (doc != null) {
	r = doc.getBounds();
      }
      if (r == null) {
	DrawCanvas canvas = view.getCanvas();
	r = canvas.getVirtualCanvasRectangle();
      }
      marginWidth = (int) view.getMarginWidth();
      marginHeight = (int) view.getMarginHeight();

      rectHeight = (int) r.getHeight();
      rectWidth = (int) r.getWidth();
      rectX = (int) r.getX();
      rectY = (int) r.getY();

      if (includeMargin) {
	rectX -= marginWidth;
	rectWidth += 2 * marginWidth;
	rectY -= marginHeight;
	rectHeight += 2 * marginHeight;
      }

      nY = (int) Math.ceil((float) rectHeight / (float) pageHeight);
      nX = (int) Math.ceil((float) rectWidth / (float) pageWidth);
      nPages = nX * nY;

      if (debug) {
	System.out.println("PrintManager: pageX=" + pageX + " ("
	    + (pageX / 72f) + ") pageY=" + pageY + " (" + (pageY / 72f)
	    + ") pageWidth=" + pageWidth + " (" + (pageWidth / 72f)
	    + ") pageHeight=" + pageHeight + " (" + (pageHeight / 72f) + ")"
	    + " nX=" + nX + " nY=" + nY + " nPages=" + nPages);
      }
    }
  }

  public void showPreviewDialog() {
    reset();
    if (previewDialog == null) {
      previewDialog = new PreviewDialog();
    } else {
      previewDialog.reset();
    }
    previewDialog.showDialog();
  }

  public int printPage(Graphics g, int pageIndex) {
    if (view != null && pf != null) {
      if (pageIndex >= 0 && pageIndex < nPages) {
	int nx = pageIndex % nX;
	int ny = pageIndex / nX;

	Graphics2D g2 = (Graphics2D) g;
	AffineTransform t = g2.getTransform();

	int x0 = rectX + nx * pageWidth;
	int y0 = rectY + ny * pageHeight;
	g2.translate(pageX - x0, pageY - y0);
	g2.setClip(x0, y0, pageWidth, pageHeight);

	// draw page frame
	if (drawPageFrame) {
	  g2.setColor(Color.lightGray);
	  g2.drawRect(x0, y0, pageWidth, pageHeight);
	}
	if (View.isWaterMark()) {
	  String waterMark1 = AbstractEncoder.WATER_MARK_STRING1 + " "
	      + AbstractEncoder.WATER_MARK_STRING2;
	  String waterMark2 = AbstractEncoder.WATER_MARK_STRING2 + " "
	      + AbstractEncoder.WATER_MARK_STRING1;
	  g2.setColor(DrawShapeConstants.waterMarkColor);
	  // g2.drawRect(x0, y0, pageWidth, pageHeight);
	  g2.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));
	  int i = 0;
	  for (float x = x0, y = y0; y < y0 + pageHeight; y += 44, x += 36, i++) {
	    if (i % 2 == 0) {
	      g2.drawString(waterMark1, x, y + 36);
	    } else {
	      g2.drawString(waterMark2, x, y + 36);
	    }
	  }
	}

	view.paintCanvas(g2, null, true);

	g2.setTransform(t);
	/*
         * ResourceManager resourceManager = view.getResourceManager();
         * view.displayMessage(resourceManager.getResourceString("Printing.message.1") + " " +
         * (pageIndex + 1) + " " +
         * resourceManager.getResourceString("Printing.message.2") + " " +
         * nPages);
         */
	return Printable.PAGE_EXISTS;
      }
    }
    return Printable.NO_SUCH_PAGE;
  }

  protected View view;

  protected PageFormat pf;

  protected int paperWidth;

  protected int paperHeight;

  protected int pageWidth;

  protected int pageHeight;

  protected int pageX;

  protected int pageY;

  protected int marginHeight;

  protected int marginWidth;

  protected int rectHeight;

  protected int rectWidth;

  protected int rectX;

  protected int rectY;

  protected int nY;

  protected int nX;

  protected int nPages;

  protected boolean includeMargin = true;

  protected PreviewDialog previewDialog = null;

  protected static final boolean drawPageFrame = false;

  protected static final boolean debug = false;

  class PreviewDialog extends JDialog {

    public PreviewDialog() {
      super((JFrame) null, "Print Preview");

      int w = paperWidth / 2;
      int h = paperHeight / 2;
      BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
      g2 = bi.createGraphics();
      drawPage(0);

      JLabel page = new JLabel(new ImageIcon(bi));
      JScrollPane scroll = new JScrollPane(page);
      getContentPane().add(scroll, BorderLayout.CENTER);

      JPanel top = new JPanel();
      top.add(new JLabel("Preview page: "));
      pageChoice = new JComboBox();
      for (int i = 1; i <= nPages; i++) {
	pageChoice.addItem(Integer.toString(i));
      }
      top.add(pageChoice);
      pageChoice.addItemListener(new ItemListener() {
	public void itemStateChanged(ItemEvent e) {
	  if (e.getStateChange() == ItemEvent.SELECTED) {
	    Object src = e.getSource();
	    if (src instanceof JComboBox) {
	      JComboBox pageChoice = (JComboBox) src;
	      drawPage(pageChoice.getSelectedIndex());
	      getContentPane().repaint();
	    }
	  }
	}
      });
      JButton closeButton = new JButton("Close");
      closeButton.addActionListener(new ActionListener() {
	public void actionPerformed(ActionEvent e) {
	  // PreviewDialog.this.setVisible(false);
	  setVisible(false);
	}
      });
      top.add(closeButton);
      getContentPane().add(top, BorderLayout.NORTH);

      getContentPane().add(message, BorderLayout.SOUTH);
    }

    public void reset() {
      pageChoice.removeAllItems();
      for (int i = 1; i <= nPages; i++) {
	pageChoice.addItem(Integer.toString(i));
      }
    }

    public void showDialog() {
      pack();
      Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
      Dimension dialogSize = getSize();
      setLocation(screenSize.width / 2 - dialogSize.width / 2,
	  screenSize.height / 2 - dialogSize.height / 2);
      setVisible(true);
    }

    public void drawPage(int pageIndex) {
      if (g2 != null && pageIndex >= 0 && pageIndex < nPages) {
	int nx = pageIndex % nX;
	int ny = pageIndex / nX;

	if (debug) {
	  System.out.println("PrintPreviewManager.drawPage(): pageIndex="
	      + pageIndex + " nx=" + nx + " ny=" + ny);
	}

	AffineTransform t = g2.getTransform();
	g2.scale(0.5, 0.5);

	int x0 = rectX + nx * pageWidth;
	int y0 = rectY + ny * pageHeight;
	g2.translate(pageX - x0, pageY - y0);

	// draw page background
	g2.setColor(view.getBackgroundColor());
	g2.fillRect(x0 - pageX, y0 - pageY, paperWidth, paperHeight);

	// draw page frame
	g2.setColor(Color.lightGray);
	g2.drawRect(x0, y0, pageWidth, pageHeight);
	g2.setClip(x0, y0, pageWidth, pageHeight);

	view.paintCanvas(g2, null, true);

	g2.setTransform(t);
	message.setText("Preview page " + (pageIndex + 1) + " of " + nPages
	    + " at row " + (ny + 1) + " column " + (nx + 1));
      }
    }

    protected Graphics2D g2;

    protected JLabel message = new JLabel("");

    protected JComboBox pageChoice;

  }

}
